﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Specifications</title>
<link type="text/css" rel="stylesheet" href="bootstrap.min.css" />
</head>

<body>

<div class="document-contents">

<h3>Introduction</h3>
<p><strong><em>Specification pattern</em></strong><em> is a particular software design pattern, whereby business rules can be recombined by chaining the business rules together using boolean logic</em> 
(<a href="https://en.wikipedia.org/wiki/Specification_pattern" target="_blank">Wikipedia</a>).</p>
	<p>In pratical, it's mostly used <strong>to define reusable filters </strong>
	for entities or other business objects.</p>
	<h4>Example</h4>
	<p>In this section, we will see <strong>the need for specification pattern</strong>. 
	This section is generic and not related to ABP's implementation.</p>
	<p>Assume that you have a service 
	method that calculates total count of your customers as shown below:</p>
	<pre lang="cs">public class CustomerManager
{
    public int GetCustomerCount()
    {
        //TODO...
        return 0;
    }
}</pre>
	<p>You probably will want to get customer count by a filter. For example, 
	you may have <strong>premium customers</strong> (which have balance more 
	than $100,000) or you may want to filter customers just by <strong>
	registration year</strong>. Then you can create other methods like <em>
	GetPremiumCustomerCount()</em>, <em>
	GetCustomerCountRegisteredInYear(int year)</em>, <em>
	GetPremiumCustomerCountRegisteredInYear(int year)</em> and more. As you have 
	more criteria, it's not possible to create a combination for every 
	possibility.</p>
	<p>One solution to this problem is the <strong>specification pattern</strong>. We could 
	create a single method that gets <strong>a parameter as the filter</strong>:</p>
	<pre lang="cs">public class CustomerManager
{
    private readonly IRepository&lt;Customer&gt; _customerRepository;

    public CustomerManager(IRepository&lt;Customer&gt; customerRepository)
    {
        _customerRepository = customerRepository;
    }

    public int GetCustomerCount(<strong>ISpecification&lt;Customer&gt; spec</strong>)
    {
        var customers = _customerRepository.GetAllList();

        var customerCount = 0;
        
        foreach (var customer in customers)
        {
            if (<strong>spec.IsSatisfiedBy(customer)</strong>)
            {
                customerCount++;
            }
        }

        return customerCount;
    }
}</pre>
	<p>Thus, we can get any object as parameter that implements <strong>
	ISpecification&lt;Customer&gt;</strong> interface which is defined as shown below:</p>
	<pre lang="cs">public interface ISpecification&lt;T&gt;
{
    <strong>bool IsSatisfiedBy(T obj);</strong>
}</pre>
	<p>And we can call <strong>IsSatisfiedBy</strong> with a customer to test if 
	this customer is intented. Thus, we can use same GetCustomerCount with 
	different filters <strong>without changing the method</strong> itself.</p>
	<p>While this solution is pretty fine in theory, it should be improved to 
	better work in C#. For instance, it's <strong>not efficient</strong> to get 
	all customers from database to check if they satisfy the given 
	specification/condition. In the next section, we will see ABP's 
	implementation which overcome this problem.</p>
	<h3>Creating Specification Classes</h3>
	<p>ABP defines the ISpecification interface as shown below:</p>
	<pre lang="cs">public interface ISpecification&lt;T&gt;
{
    bool IsSatisfiedBy(T obj);

    Expression&lt;Func&lt;T, bool&gt;&gt; ToExpression();
}</pre>
	<p>Adds a <strong>ToExpression()</strong> method which returns an 
	expression and used to better integrate with <strong>IQueryable</strong> and
	<strong>Expression trees</strong>. Thus, we can easily pass a specification 
	to a repository to apply a filter in the database level.</p>
	<p>We generally inherit from <strong>Specification&lt;T&gt; class</strong> instead 
	of directly implementing ISpecification&lt;T&gt; interface. Specification class 
	automatically implements IsSatisfiedBy method. So, we only need to define 
	ToExpression. Let's create some specification classes:</p>
	<pre lang="cs">//Customers with $100,000+ balance are assumed as PREMIUM customers.
public class PremiumCustomerSpecification : Specification&lt;Customer&gt;
{
    public override Expression&lt;Func&lt;Customer, bool&gt;&gt; ToExpression()
    {
        return (customer) =&gt; (customer.Balance &gt;= 100000);
    }
}

//A parametric specification example.
public class CustomerRegistrationYearSpecification : Specification&lt;Customer&gt;
{
    public int Year { get; }

    public CustomerRegistrationYearSpecification(int year)
    {
        Year = year;
    }

    public override Expression&lt;Func&lt;Customer, bool&gt;&gt; ToExpression()
    {
        return (customer) =&gt; (customer.CreationYear == Year);
    }
}</pre>
	<p>As you see, we just implemented simple <strong>lambda expressions</strong> 
	to define specifications. Let's use these specifications to get count of 
	customers:</p>
	<pre lang="cs">count = customerManager.GetCustomerCount(new PremiumCustomerSpecification());
count = customerManager.GetCustomerCount(new CustomerRegistrationYearSpecification(2017));
</pre>
	<h3>Using Specification With Repository</h3>
	<p>Now, we can <strong>optimize</strong> CustomerManager to <strong>apply filter in the database</strong>:</p>
	<pre lang="cs">public class CustomerManager
{
    private readonly IRepository&lt;Customer&gt; _customerRepository;

    public CustomerManager(IRepository&lt;Customer&gt; customerRepository)
    {
        _customerRepository = customerRepository;
    }

    public int GetCustomerCount(ISpecification&lt;Customer&gt; spec)
    {
        return _customerRepository.Count(<strong>spec.ToExpression()</strong>);
    }
}</pre>
	<p>It's that simple. We can pass any specification to repositories since
	<a href="Repositories.html">repositories</a> can work with expressions as 
	filters. In this example, CustomerManager is unnecessary since we could 
	directly use repository with the specification to query database. But think 
	that we want to execute a business operation on some customers. In that 
	case, we could use specifications with a domain service to specify customers 
	to work on.</p>
	<h3>Composing Specifications</h3>
	<p>One powerful feature of specifications is that they are <strong>composable</strong> with
	<strong>And, Or, Not</strong> and <strong>AndNot</strong> extension methods. 
	Example:</p>
	<pre lang="cs">var count = customerManager.GetCustomerCount(<strong>new PremiumCustomerSpecification().And(new CustomerRegistrationYearSpecification(2017))</strong>);</pre>
	<p>We can even create a new specification class from existing 
	specifications:</p>
	<pre lang="cs">public class NewPremiumCustomersSpecification : <strong>AndSpecification&lt;Customer&gt;</strong>
{
    public NewPremiumCustomersSpecification() 
        : base(<strong>new PremiumCustomerSpecification(), new CustomerRegistrationYearSpecification(2017)</strong>)
    {
    }
}</pre>
	<p><strong>AndSpecification</strong> is a subclass of <strong>Specification</strong> 
	class which satisfies only if both specifications are satisfied. Then we can 
	use NewPremiumCustomersSpecification just like any other specification:</p>
	<pre lang="cs">var count = customerManager.GetCustomerCount(<strong>new NewPremiumCustomersSpecification()</strong>);</pre>
	<h3>Discussion</h3>
	<p>While specification pattern is older than C# lambda expressions, it's 
	generally compared to expressions. Some developers may think it's not needed 
	anymore and we can directly pass expressions to a repository or to a domain 
	service as shown below:</p>
	<pre lang="cs">var count = _customerRepository.Count(<strong>c =&gt; c.Balance &gt; 100000 &amp;&amp; c.CreationYear == 2017</strong>);</pre>
	<p>Since ABP's <a href="Repositories.html">Repository</a> supports 
	expessions, this is completely a valid usage. You don't have to define or 
	use any specification in your application and you can go with expressions. 
	So, what's the point of specification? Why and when should we consider to 
	use them?</p>
	<h4>When To Use?</h4>
	<p>Some benefits of using specifications:</p>
	<ul>
		<li><strong>Reusabe</strong>: Think that you need to PremiumCustomer 
		filter in many places in your code base. If you go with expressions and 
		not create a specification, what happens if you later change "Premium 
		Customer" definition (say, you want to change minimum balance from 
		$100,000 to $250,000 and add another condition like to be a customer 
		older than 3). If you used specification, you just change a single 
		class. If you used (copy/paste) same expression, you need to change all 
		of them.</li>
		<li><strong>Composable</strong>: You can combine multiple specification 
		to create new specifications. This is another type of reusability.</li>
		<li><strong>Named</strong>: PremiumCustomerSpecification better explains 
		the intent rather than a complex expression. So, if you have an 
		expression that is meaningful in your business, consider to use 
		specifications.</li>
		<li><strong>Testable</strong>: A specification is separately (and 
		easily) testable object.</li>
	</ul>
	<h4>When To Not Use?</h4>
	<ul>
		<li><strong>Non business expressions</strong>: You can consider to not 
		use specifications for non business related expressions and operations.</li>
		<li><strong>Reporting</strong>: If you are just creating a report do not 
		create specifications, but directly use IQueryable. Actually, you can 
		even use plain SQL, Views or another tool for reporting. DDD does not 
		care on reporting much and getting querying benefits of underlying data 
		store can be important from performance point of view.</li>
	</ul>

</div>

</body>

</html>
